home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / gtlayout-source.lha / LTP_PopupClass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  23.2 KB  |  1,147 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1996 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. #if defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
  15.  
  16. #define PIF_SingleActive    (1 << 0)
  17. #define PIF_ArrowUp            (1 << 1)
  18. #define PIF_ArrowDown        (1 << 2)
  19.  
  20. STATIC VOID
  21. DrawArrow(struct RastPort *RPort,LONG Left,LONG Top,LONG ArrowWidth,LONG ArrowHeight,LONG Dir)
  22. {
  23.     LONG i,Width,Start,Pos;
  24.  
  25.     for(i = 0 ; i < ArrowHeight ; i++)
  26.     {
  27.         Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
  28.  
  29.         if(Width < ArrowWidth)
  30.             Width++;
  31.  
  32.         Start = Left + (ArrowWidth - Width) / 2;
  33.  
  34.         if(Dir < 0)
  35.             Pos = Top + i;
  36.         else
  37.             Pos = Top + ArrowHeight - 1 - i;
  38.  
  39.         LTP_DrawLine(RPort,Start,Pos,Start + Width - 1,Pos);
  40.     }
  41. }
  42.  
  43. STATIC VOID
  44. DrawContainer(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height,struct GadgetInfo *GadgetInfo,PopInfo *Info,UWORD Highlight)
  45. {
  46.     LONG Shine,Shadow,Txt,Fill;
  47.     UWORD *Pens;
  48.  
  49.     Pens = GadgetInfo->gi_DrInfo->dri_Pens;
  50.  
  51.     if(Highlight)
  52.     {
  53.         Shine    = Pens[SHADOWPEN];
  54.         Shadow    = Pens[SHINEPEN];
  55.         Txt        = Pens[FILLTEXTPEN];
  56.         Fill    = Pens[FILLPEN];
  57.     }
  58.     else
  59.     {
  60.         Shine    = Pens[SHINEPEN];
  61.         Shadow    = Pens[SHADOWPEN];
  62.         Txt        = Pens[TEXTPEN];
  63.         Fill    = Pens[BACKGROUNDPEN];
  64.     }
  65.  
  66.     LTP_SetPens(RPort,Fill,0,JAM1);
  67.  
  68.     LTP_FillBox(RPort,Left + 2,Top + 1,Width - 4,Height - 2);
  69.  
  70.     LTP_RenderBevel(RPort,Pens,Left,Top,Width,Height,Highlight,2);
  71.  
  72.     LTP_SetAPen(RPort,Shadow);
  73.     LTP_DrawLine(RPort,Left + Info->MarkLeft,Top + 2,Left + Info->MarkLeft,Top + Height - 3);
  74.  
  75.     LTP_SetAPen(RPort,Shine);
  76.     LTP_DrawLine(RPort,Left + Info->MarkLeft + 1,Top + 2,Left + Info->MarkLeft + 1,Top + Height - 3);
  77.  
  78.     SetFont(RPort,Info->Font);
  79.     LTP_SetAPen(RPort,Txt);
  80.  
  81.     DrawArrow(RPort,Left + 4,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,1);
  82.  
  83.     LTP_PrintText(RPort,Info->Labels[Info->Active],Info->ActiveLen,Left + Info->LabelLeft,Top + Info->LabelTop);
  84. }
  85.  
  86. STATIC VOID
  87. DrawOneBox(PopInfo *Info,LONG Top,LONG Index)
  88. {
  89.     struct RastPort    *RPort;
  90.     LONG             Len;
  91.     LONG             Extra;
  92.     STRPTR             Label;
  93.  
  94.     Label = Info->Labels[Index];
  95.  
  96.     RPort = Info->Window->RPort;
  97.  
  98.     if((Len = strlen(Label)) > Info->MaxLen)
  99.         Len = Info->MaxLen;
  100.  
  101.     if(Info->CheckGlyph)
  102.         Extra = Info->CheckGlyph->Width + 2;
  103.     else
  104.         Extra = 0;
  105.  
  106.     LTP_PrintText(RPort,Label,Len,6 + Extra,Top + Info->LineTop);
  107.  
  108.     if(Extra && Index == Info->InitialActive)
  109.         LTP_DrawCheckGlyph(RPort,6,Top + Info->LineTop,Info->CheckGlyph,Index == Info->LastLabelDrawn);
  110. }
  111.  
  112. STATIC VOID
  113. DrawOneGlyph(PopInfo *Info,LONG Top,LONG Dir,UWORD *Pens)
  114. {
  115.     struct RastPort *RPort;
  116.  
  117.     RPort = Info->Window->RPort;
  118.  
  119.     if(Pens)
  120.     {
  121.         LTP_SetAPen(RPort,Info->MenuBack);
  122.         LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
  123.         LTP_SetAPen(RPort,Info->MenuText);
  124.     }
  125.  
  126.     DrawArrow(RPort,6,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,Dir);
  127. }
  128.  
  129. STATIC VOID
  130. BoxRender(PopInfo *Info,UWORD *Pens,LONG Active,BOOL FullRefresh,BOOL Highlight,LONG Dir)
  131. {
  132.     struct RastPort *RPort = Info->Window->RPort;
  133.  
  134.     if(FullRefresh)
  135.     {
  136.         LONG Index,Top;
  137.         LONG Width,Height;
  138.  
  139.         LTP_SetPens(RPort,Info->MenuBack,0,JAM1);
  140.  
  141.         Width    = Info->Window->Width;
  142.         Height    = Info->Window->Height;
  143.  
  144.         LTP_FillBox(RPort,2,1,Width - 4,Height - 2);
  145.  
  146.         LTP_SetAPen(RPort,Info->MenuText);
  147.  
  148.         LTP_PolyDraw(RPort,5,
  149.             1,1,
  150.             1,Height - 2,
  151.             0,Height - 2,
  152.             0,0,
  153.             Width - 1,0);
  154.  
  155.         LTP_PolyDraw(RPort,5,
  156.             0,Height - 1,
  157.             Width - 1,Height - 1,
  158.             Width - 1,1,
  159.             Width - 2,1,
  160.             Width - 2,Height - 2);
  161.  
  162.         Index    = Info->TopMost;
  163.         Top        = 2;
  164.         Height    = Info->BoxHeight;
  165.  
  166.         Info->Flags &= ~(PIF_ArrowUp | PIF_ArrowDown);
  167.  
  168.         if(Info->TopMost > 0 && Active != Info->TopMost && Info->BoxLines > 2)
  169.         {
  170.             Info->Flags |= PIF_ArrowUp;
  171.  
  172.             Index    += 1;
  173.             Top        += Info->SingleHeight;
  174.             Height    -= Info->SingleHeight;
  175.         }
  176.  
  177.         if(Info->TopMost + Info->BoxLines < Info->NumLabels && Active != Info->TopMost + Info->BoxLines - 1 && Info->BoxLines > 2)
  178.         {
  179.             Info->Flags |= PIF_ArrowDown;
  180.  
  181.             Height -= Info->SingleHeight;
  182.         }
  183.  
  184.         Info->LastLabelDrawn = Active;    // IMPORTANT: must be set up here to DrawOneBox can find it
  185.  
  186.         for( ; Index < Info->NumLabels && Height > 0 ; Index++, Top += Info->SingleHeight, Height -= Info->SingleHeight)
  187.         {
  188.             if(Index == Active)
  189.             {
  190.                 LTP_SetAPen(RPort,Info->MenuBackSelect);
  191.                 LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
  192.  
  193.                 LTP_SetAPen(RPort,Info->MenuTextSelect);
  194.                 DrawOneBox(Info,Top,Index);
  195.  
  196.                 LTP_SetAPen(RPort,Info->MenuText);
  197.             }
  198.             else
  199.                 DrawOneBox(Info,Top,Index);
  200.         }
  201.  
  202.         if(Info->Flags & PIF_ArrowUp)
  203.             DrawOneGlyph(Info,2,-1,NULL);
  204.  
  205.         if(Info->Flags & PIF_ArrowDown)
  206.             DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,NULL);
  207.  
  208.         Info->LastDrawn = 2 + (Active - Info->TopMost) * Info->SingleHeight;
  209.     }
  210.     else
  211.     {
  212.         if(Info->LastLabelDrawn != -1)
  213.         {
  214.             LONG Top = Info->LastDrawn,Last = Info->LastLabelDrawn;
  215.  
  216.             Info->LastLabelDrawn = -1;
  217.  
  218.             LTP_SetPens(RPort,Info->MenuBack,0,JAM1);
  219.             LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
  220.             LTP_SetAPen(RPort,Info->MenuText);
  221.  
  222.             DrawOneBox(Info,Top,Last);
  223.         }
  224.  
  225.         Info->LastDrawn = -1;
  226.  
  227.         if(Active >= 0)
  228.         {
  229.             LONG Top,NewActive;
  230.  
  231.             NewActive    = Active - Info->TopMost;
  232.             Top            = 2 + NewActive * Info->SingleHeight;
  233.  
  234.             if(Top >= 2 && Top < Info->BoxHeight + 2)
  235.             {
  236.                 LONG Pen;
  237.  
  238.                 if(Dir != 0)
  239.                     Highlight = FALSE;
  240.  
  241.                 if(Highlight)
  242.                 {
  243.                     Pen = Info->MenuBackSelect;
  244.  
  245.                     Info->LastDrawn            = Top;
  246.                     Info->LastLabelDrawn    = Active;
  247.                 }
  248.                 else
  249.                     Pen = Info->MenuBack;
  250.  
  251.                 LTP_SetPens(RPort,Pen,0,JAM1);
  252.                 LTP_FillBox(RPort,4,Top,Info->SingleWidth,Info->SingleHeight);
  253.  
  254.                 if(Highlight)
  255.                     Pen = Info->MenuTextSelect;
  256.                 else
  257.                     Pen = Info->MenuText;
  258.  
  259.                 LTP_SetAPen(RPort,Pen);
  260.  
  261.                 if(Dir == 0)
  262.                     DrawOneBox(Info,Top,Active);
  263.                 else
  264.                     DrawOneGlyph(Info,Top,Dir,NULL);
  265.             }
  266.         }
  267.     }
  268. }
  269.  
  270. STATIC ULONG
  271. InputMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  272. {
  273.     PopInfo    *Info    = INST_DATA(class,gadget);
  274.     ULONG     Result    = GMR_MEACTIVE;
  275.     BOOL     Done    = FALSE;
  276.     BOOL     Redraw    = FALSE;
  277.  
  278.     if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
  279.     {
  280.         UWORD Code = InputInfo->gpi_IEvent->ie_Code;
  281.  
  282.         if(Code == MENUDOWN)
  283.         {
  284.             Result    = GMR_NOREUSE;
  285.             Done    = TRUE;
  286.  
  287.             Info->Active = Info->InitialActive;
  288.         }
  289.         else
  290.         {
  291.             if(Code == SELECTUP)
  292.             {
  293.                 Done = TRUE;
  294.  
  295.                 if(Info->Active < 0)
  296.                 {
  297.                     Result = GMR_NOREUSE;
  298.  
  299.                     Info->Active = Info->InitialActive;
  300.                 }
  301.                 else
  302.                 {
  303.                     LONG Len;
  304.  
  305.                     Result = GMR_NOREUSE | GMR_VERIFY;
  306.  
  307.                     if(Info->Flags & PIF_SingleActive)
  308.                     {
  309.                         LONG Width,Height;
  310.                         LONG x,y;
  311.  
  312.                         x = InputInfo->gpi_Mouse.X;
  313.                         y = InputInfo->gpi_Mouse.Y;
  314.  
  315.                         Width    = gadget->Width;
  316.                         Height    = gadget->Height;
  317.  
  318.                         if(x >= 0 && y >= 0 && x < Width && y < Height)
  319.                         {
  320.                             if(InputInfo->gpi_IEvent->ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  321.                                 Info->Active--;
  322.                             else
  323.                                 Info->Active++;
  324.  
  325.                             if(Info->Active >= Info->NumLabels)
  326.                                 Info->Active = 0;
  327.                             else
  328.                             {
  329.                                 if(Info->Active < 0)
  330.                                     Info->Active = Info->NumLabels - 1;
  331.                             }
  332.                         }
  333.                         else
  334.                         {
  335.                             Result = GMR_NOREUSE;
  336.  
  337.                             Info->Active = Info->InitialActive;
  338.                         }
  339.                     }
  340.  
  341.                     Len = strlen(Info->Labels[Info->Active]);
  342.  
  343.                     if(Len > Info->MaxLen)
  344.                         Len = Info->MaxLen;
  345.  
  346.                     Info->ActiveLen = Len;
  347.  
  348.                     *InputInfo->gpi_Termination = Info->Active;
  349.                 }
  350.             }
  351.             else
  352.             {
  353.                 if(Info->Flags & PIF_SingleActive)
  354.                 {
  355.                     LONG Width,Height;
  356.                     LONG x,y;
  357.                     BOOL RefreshIt = FALSE;
  358.  
  359.                     x = InputInfo->gpi_Mouse.X;
  360.                     y = InputInfo->gpi_Mouse.Y;
  361.  
  362.                     Width    = gadget->Width;
  363.                     Height    = gadget->Height;
  364.  
  365.                     if(x < 0 || y < 0 || x >= Width || y >= Height)
  366.                     {
  367.                         if(gadget->Flags & GFLG_SELECTED)
  368.                             RefreshIt = TRUE;
  369.                     }
  370.                     else
  371.                     {
  372.                         if(!(gadget->Flags & GFLG_SELECTED))
  373.                             RefreshIt = TRUE;
  374.                     }
  375.  
  376.                     if(RefreshIt)
  377.                     {
  378.                         gadget->Flags ^= GFLG_SELECTED;
  379.  
  380.                         Redraw = TRUE;
  381.                     }
  382.                 }
  383.             }
  384.         }
  385.  
  386.         if(Done)
  387.         {
  388.             if(gadget->Flags & GFLG_SELECTED)
  389.             {
  390.                 gadget->Flags &= ~GFLG_SELECTED;
  391.                 Redraw = TRUE;
  392.             }
  393.  
  394.             if(Info->Window)
  395.             {
  396.                 CloseWindow(Info->Window);
  397.                 Info->Window = NULL;
  398.             }
  399.  
  400.             LTP_DeleteCheckGlyph(Info->CheckGlyph);
  401.             Info->CheckGlyph = NULL;
  402.  
  403.             Info->Flags &= ~PIF_SingleActive;
  404.         }
  405.     }
  406.  
  407.     if(!Done && Info->Window)
  408.     {
  409.         LONG    NewActive = 0;
  410.         LONG    x,y;
  411.         LONG    Dir = 0;
  412.         LONG    From,To;
  413.  
  414.         x = InputInfo->gpi_GInfo->gi_Screen->MouseX - Info->BoxLeft;
  415.         y = InputInfo->gpi_GInfo->gi_Screen->MouseY - Info->BoxTop;
  416.  
  417.         if(x < 0 || x >= Info->BoxWidth)
  418.             NewActive = -1;
  419.         else
  420.         {
  421.             LONG Margin;
  422.  
  423.             if(Info->Flags & (PIF_ArrowUp | PIF_ArrowDown))
  424.                 Margin = Info->SingleHeight;
  425.             else
  426.                 Margin = (Info->SingleHeight + 3) / 4;
  427.  
  428.                 // Scroll up?
  429.  
  430.             if(y < Margin)
  431.             {
  432.                 if(y < 0)
  433.                     NewActive = -1;
  434.                 else
  435.                 {
  436.                         // Topmost line concealed?
  437.  
  438.                     if(Info->TopMost > 0)
  439.                     {
  440.                         Info->TopMost--;
  441.  
  442.                         From    = 2;
  443.                         To        = 2 + Info->BoxHeight - 1;
  444.  
  445.                         Dir = -Info->SingleHeight;
  446.                     }
  447.                 }
  448.             }
  449.             else
  450.             {
  451.                 LONG Last;
  452.  
  453.                 Last = Info->NumLabels - Info->TopMost;
  454.  
  455.                 if(Last < Info->BoxLines)
  456.                     Last = Last * Info->SingleHeight;
  457.                 else
  458.                     Last = Info->BoxHeight;
  459.  
  460.                     // Scroll up?
  461.  
  462.                 if(y >= Last - Margin)
  463.                 {
  464.                     if(y >= Last)
  465.                         NewActive = -1;
  466.                     else
  467.                     {
  468.                             // Last line concealed?
  469.  
  470.                         if(Info->TopMost + Info->BoxLines < Info->NumLabels)
  471.                         {
  472.                             Info->TopMost++;
  473.  
  474.                             From    = 2;
  475.                             To        = 2 + Info->BoxHeight - 1;
  476.  
  477.                             Dir = Info->SingleHeight;
  478.                         }
  479.                     }
  480.                 }
  481.             }
  482.  
  483.             if(NewActive != -1)
  484.             {
  485.                 NewActive = Info->TopMost + y / Info->SingleHeight;
  486.  
  487.                 if(NewActive < 0)
  488.                     NewActive = 0;
  489.                 else
  490.                 {
  491.                     if(NewActive >= Info->NumLabels)
  492.                         NewActive = Info->NumLabels - 1;
  493.                 }
  494.             }
  495.         }
  496.  
  497.         if(NewActive != Info->Active || Dir != 0)
  498.         {
  499.             LONG     Arrow;
  500.             UWORD    *Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  501.  
  502.             if(Dir != 0)
  503.             {
  504.                 struct RastPort *RPort = Info->Window->RPort;
  505.  
  506.                 Arrow = (NewActive == Info->TopMost) ? -1 : 1;
  507.  
  508.                 BoxRender(Info,Pens,-1,FALSE,FALSE,0);
  509.  
  510.                 if(Info->Flags & PIF_ArrowUp)
  511.                     From += Info->SingleHeight;
  512.  
  513.                 if(Info->Flags & PIF_ArrowDown)
  514.                     To -= Info->SingleHeight;
  515.  
  516.                 SetBPen(RPort,Pens[BACKGROUNDPEN]);
  517.                 ScrollRaster(RPort,0,Dir,4,From,4 + Info->BoxWidth - 1,To);
  518.  
  519.                 if(Dir < 0)
  520.                     BoxRender(Info,Pens,Info->TopMost + 1,FALSE,FALSE,0);
  521.                 else
  522.                     BoxRender(Info,Pens,Info->TopMost + Info->BoxLines - 2,FALSE,FALSE,0);
  523.  
  524.                 if(!Info->TopMost || Info->BoxLines < 3)
  525.                 {
  526.                     Info->Flags &= ~PIF_ArrowUp;
  527.  
  528.                     Arrow = 0;
  529.                 }
  530.                 else
  531.                 {
  532.                     if(!(Info->Flags & PIF_ArrowUp))
  533.                     {
  534.                         Info->Flags |= PIF_ArrowUp;
  535.  
  536.                         DrawOneGlyph(Info,2,-1,Pens);
  537.                     }
  538.                 }
  539.  
  540.                 if(Info->TopMost + Info->BoxLines >= Info->NumLabels || Info->BoxLines < 3)
  541.                 {
  542.                     Info->Flags &= ~PIF_ArrowDown;
  543.  
  544.                     Arrow = 0;
  545.                 }
  546.                 else
  547.                 {
  548.                     if(!(Info->Flags & PIF_ArrowDown))
  549.                     {
  550.                         Info->Flags |= PIF_ArrowDown;
  551.  
  552.                         DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,Pens);
  553.                     }
  554.                 }
  555.             }
  556.             else
  557.                 Arrow = 0;
  558.  
  559.             Info->Active = NewActive;
  560.  
  561.             BoxRender(Info,Pens,NewActive,FALSE,TRUE,Arrow);
  562.         }
  563.     }
  564.  
  565.     if(Redraw)
  566.     {
  567.         struct RastPort    *RPort;
  568.  
  569.         if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  570.         {
  571.             DoMethod((Object *)gadget,GM_RENDER,InputInfo->gpi_GInfo,RPort,GREDRAW_UPDATE);
  572.             ReleaseGIRPort(RPort);
  573.         }
  574.     }
  575.  
  576.     return(Result);
  577. }
  578.  
  579. STATIC VOID
  580. SetMethod(struct IClass *class,struct Gadget *gadget,struct opSet *SetInfo)
  581. {
  582.     PopInfo            *Info = INST_DATA(class,gadget);
  583.     struct TagItem    *This;
  584.     LONG             NewActive;
  585.     STRPTR            *NewLabels;
  586.     UWORD             Flags = gadget -> Flags;
  587.     BOOL             NeedRefresh = FALSE;
  588.  
  589.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  590.  
  591.     if(This = FindTagItem(GA_Disabled,SetInfo->ops_AttrList))
  592.     {
  593.         if(This -> ti_Data && !(Flags & GFLG_DISABLED) || !This -> ti_Data && (Flags & GFLG_DISABLED))
  594.             NeedRefresh = TRUE;
  595.     }
  596.  
  597.     NewLabels = (STRPTR *)GetTagData(PIA_Labels,NULL,SetInfo->ops_AttrList);
  598.  
  599.     if(This = FindTagItem(PIA_Active,SetInfo->ops_AttrList))
  600.     {
  601.         LONG NumLabels = Info->NumLabels;
  602.  
  603.         if(NewLabels)
  604.             for(NumLabels = 0 ; NewLabels[NumLabels] ; NumLabels++);
  605.  
  606.         NewActive = (LONG)This->ti_Data;
  607.  
  608.         if(NewActive < 0)
  609.             NewActive = 0;
  610.         else
  611.         {
  612.             if(NewActive >= NumLabels)
  613.                 NewActive = NumLabels - 1;
  614.         }
  615.     }
  616.     else
  617.         NewActive = -1;
  618.  
  619.     if((NewActive != Info->Active && NewActive != -1) || NewLabels)
  620.     {
  621.         if(NewLabels == (STRPTR *)~0)
  622.             Info->Blocked = TRUE;
  623.         else
  624.         {
  625.             struct RastPort *RPort;
  626.  
  627.             Info->Blocked = FALSE;
  628.  
  629.             if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  630.             {
  631.                 LONG     Len;
  632.                 STRPTR    *Labels;
  633.                 LONG     NumLabels;
  634.                 LONG     MaxLen,ActiveLen;
  635.  
  636.                 if(NewLabels && NewLabels != (STRPTR *)~0)
  637.                 {
  638.                     struct TextExtent Extent;
  639.  
  640.                     for(NumLabels = MaxLen = 0 ; NewLabels[NumLabels] ; NumLabels++)
  641.                     {
  642.                         Len = TextFit(RPort,NewLabels[NumLabels],strlen(NewLabels[NumLabels]),&Extent,NULL,1,Info->MaxWidth,32767);
  643.  
  644.                         if(Len > MaxLen)
  645.                             MaxLen = Len;
  646.                     }
  647.  
  648.                     Labels = NewLabels;
  649.                 }
  650.                 else
  651.                 {
  652.                     Labels        = Info->Labels;
  653.                     NumLabels    = Info->NumLabels;
  654.                     MaxLen        = Info->MaxLen;
  655.                 }
  656.  
  657.                 if(NewActive == -1)
  658.                     NewActive = Info->Active;
  659.  
  660.                 if(NewActive >= NumLabels)
  661.                     NewActive = NumLabels - 1;
  662.  
  663.                 Len = strlen(Labels[NewActive]);
  664.  
  665.                 if(Len > MaxLen)
  666.                     Len = MaxLen;
  667.  
  668.                 ActiveLen = Len;
  669.  
  670.                 Info->Active    = NewActive;
  671.                 Info->ActiveLen    = ActiveLen;
  672.  
  673.                 if(NewLabels)
  674.                 {
  675.                     Info->Labels    = Labels;
  676.                     Info->NumLabels    = NumLabels;
  677.                     Info->MaxLen    = MaxLen;
  678.                 }
  679.  
  680.                 NeedRefresh = TRUE;
  681.  
  682.                 ReleaseGIRPort(RPort);
  683.             }
  684.         }
  685.     }
  686.  
  687.     if(!(gadget -> Flags & GFLG_DISABLED) && (This = FindTagItem(PIA_Highlight,SetInfo->ops_AttrList)))
  688.     {
  689.         if(This->ti_Data)
  690.             gadget->Flags |= GFLG_SELECTED;
  691.         else
  692.             gadget->Flags &= ~GFLG_SELECTED;
  693.  
  694.         NeedRefresh = TRUE;
  695.     }
  696.  
  697.     if(NeedRefresh)
  698.     {
  699.         struct RastPort *RPort;
  700.  
  701.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  702.         {
  703.             DoMethod((Object *)gadget,GM_RENDER,SetInfo->ops_GInfo,RPort,GREDRAW_UPDATE);
  704.             ReleaseGIRPort(RPort);
  705.         }
  706.     }
  707. }
  708.  
  709. STATIC ULONG
  710. RenderMethod(struct IClass *class,struct Gadget *gadget,struct gpRender *RenderInfo)
  711. {
  712.     PopInfo    *Info = INST_DATA(class,gadget);
  713.  
  714.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  715.  
  716.     DrawContainer(RenderInfo->gpr_RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,RenderInfo->gpr_GInfo,Info,gadget->Flags & GFLG_SELECTED);
  717.  
  718.     return(TRUE);
  719. }
  720.  
  721. STATIC VOID
  722. DisposeMethod(struct IClass *class,Object *object,Msg msg)
  723. {
  724.     PopInfo *Info = INST_DATA(class,object);
  725.  
  726.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  727.  
  728.     if(Info->Font)
  729.     {
  730.         CloseFont(Info->Font);
  731.         Info->Font = NULL;
  732.     }
  733.  
  734.     if(Info->Window)
  735.     {
  736.         CloseWindow(Info->Window);
  737.         Info->Window = NULL;
  738.     }
  739.  
  740.     LTP_DeleteCheckGlyph(Info->CheckGlyph);
  741.     Info->CheckGlyph = NULL;
  742. }
  743.  
  744. STATIC ULONG
  745. NewMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  746. {
  747.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  748.  
  749.     if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
  750.     {
  751.         PopInfo            *Info = INST_DATA(class,object);
  752.         struct TagItem    *Item,*TagList = SetInfo -> ops_AttrList;
  753.         struct TextAttr    *Font;
  754.         LONG             Width,Height;
  755.  
  756.         Width = Height = 0;
  757.         Font = NULL;
  758.  
  759.         memset(Info,0,sizeof(PopInfo));
  760.  
  761.         while(Item = NextTagItem(&TagList))
  762.         {
  763.             switch(Item->ti_Tag)
  764.             {
  765.                 case GA_Width:
  766.                     Width = Item->ti_Data;
  767.                     break;
  768.  
  769.                 case GA_Height:
  770.                     Height = Item->ti_Data;
  771.                     break;
  772.  
  773.                 case PIA_Labels:
  774.                     Info->Labels = (STRPTR *)Item->ti_Data;
  775.                     break;
  776.  
  777.                 case PIA_Active:
  778.                     Info->Active = (LONG)Item->ti_Data;
  779.                     break;
  780.  
  781.                 case PIA_Font:
  782.                     Font = (struct TextAttr *)Item->ti_Data;
  783.                     break;
  784.  
  785.                 case PIA_CentreActive:
  786.                     Info->CentreActive = Item->ti_Data;
  787.                     break;
  788.             }
  789.         }
  790.  
  791.         if(Font && Info->Labels && Info->Labels != (STRPTR *)~0 && Width && Height)
  792.         {
  793.             while(Info->Labels[Info->NumLabels])
  794.                 Info->NumLabels++;
  795.  
  796.             if(Info->NumLabels)
  797.             {
  798.                 if(Info->Font = OpenFont(Font))
  799.                 {
  800.                     struct RastPort __aligned RPort;
  801.  
  802.                     if(Info->Active < 0)
  803.                         Info->Active = 0;
  804.                     else
  805.                     {
  806.                         if(Info->Active >= Info->NumLabels)
  807.                             Info->Active = Info->NumLabels - 1;
  808.                     }
  809.  
  810.                     InitRastPort(&RPort);
  811.                     SetFont(&RPort,Info->Font);
  812.  
  813.                     Info->ArrowWidth    = (TextLength(&RPort,"M",1) & ~1) + 1;
  814.                     Info->ArrowHeight    = (2 * RPort.TxHeight) / 3;
  815.                     Info->ArrowTop        = (Height - Info->ArrowHeight) / 2;
  816.  
  817.                     Info->MarkLeft    = 4 + Info->ArrowWidth + 2;
  818.                     Info->MarkWidth    = Info->MarkLeft + 4;
  819. /*
  820.                     Info->PopLeft    = Info->MarkWidth - 6;
  821.                     Info->PopWidth    = Width - Info->PopLeft;
  822. */
  823.                     Info->PopLeft    = 0;
  824.                     Info->PopWidth    = Width;
  825.  
  826.                     Info->LabelTop    = (Height - RPort.TxHeight) / 2;
  827.                     Info->LabelLeft    = Info->MarkWidth;
  828.  
  829.                     Width    -= 6 + Info->MarkWidth + 6;
  830.                     Height    -= 2 + RPort.TxHeight + 2;
  831.  
  832.                     if(Width > 0 && Height >= 0)
  833.                     {
  834.                         struct TextExtent    Extent;
  835.                         LONG                i,Len,MaxLen;
  836.  
  837.                         for(i = MaxLen = 0 ; i < Info->NumLabels ; i++)
  838.                         {
  839.                             Len = TextFit(&RPort,Info->Labels[i],strlen(Info->Labels[i]),&Extent,NULL,1,Width,32767);
  840.  
  841.                             if(Len > MaxLen)
  842.                                 MaxLen = Len;
  843.                         }
  844.  
  845.                         if(MaxLen)
  846.                         {
  847.                             Len = strlen(Info->Labels[Info->Active]);
  848.  
  849.                             if(Len > MaxLen)
  850.                                 Len = MaxLen;
  851.  
  852.                             Info->ActiveLen = Len;
  853.  
  854.                             Info->MaxLen    = MaxLen;
  855.                             Info->MaxWidth    = Width;
  856.  
  857.                             return((ULONG)object);
  858.                         }
  859.                     }
  860.  
  861.                     CloseFont(Info->Font);
  862.                     Info->Font = NULL;
  863.                 }
  864.             }
  865.         }
  866.  
  867.         CoerceMethod(class,object,OM_DISPOSE);
  868.     }
  869.  
  870.     return(0);
  871. }
  872.  
  873. STATIC ULONG
  874. ActiveMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  875. {
  876.     PopInfo                *Info = INST_DATA(class,gadget);
  877.     struct RastPort        *RPort;
  878.     struct GadgetInfo    *GInfo;
  879.  
  880.     if(Info->Blocked)
  881.         return(GMR_NOREUSE);
  882.  
  883.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  884.  
  885.     GInfo = InputInfo->gpi_GInfo;
  886.  
  887.     if(RPort = ObtainGIRPort(GInfo))
  888.     {
  889.         LONG Left,Top;
  890.  
  891.         Left    = gadget->LeftEdge;
  892.         Top        = gadget->TopEdge;
  893.  
  894.         Info->Window = NULL;
  895.  
  896.         if(Info->NumLabels > 2 && InputInfo->gpi_Mouse.X >= Info->MarkLeft)
  897.         {
  898.             LONG SingleHeight,ScreenHeight,Width,Height;
  899.  
  900.             Info->Flags &= ~PIF_SingleActive;
  901.             Info->Window = NULL;
  902.  
  903.             SetFont(RPort,Info->Font);
  904.  
  905.             SingleHeight = gadget->Height;
  906.             ScreenHeight = GInfo->gi_Screen->Height;
  907.  
  908.             Info->LineTop = (SingleHeight - RPort->TxHeight) / 2;
  909.  
  910.             Width    = Info->PopWidth;
  911.             Height    = 2 + SingleHeight * Info->NumLabels + 2;
  912.  
  913.             while(Height > SingleHeight && Height > ScreenHeight)
  914.                 Height -= SingleHeight;
  915.  
  916.             if(Height > SingleHeight)
  917.             {
  918.                 struct DrawInfo *DrawInfo;
  919.                 UWORD *Pens;
  920.                 LONG LeftEdge,TopEdge;
  921.                 LONG TopMost;
  922.                 LONG Plus;
  923.  
  924.                 LeftEdge    = GInfo->gi_Window->LeftEdge + Left + Info->PopLeft;
  925.                 TopEdge        = GInfo->gi_Window->TopEdge + Top + Info->LabelTop - (2 + Info->LineTop + Info->Active * SingleHeight);
  926.                 TopMost        = 0;
  927.  
  928.                 if(Info->CentreActive)
  929.                     Plus = 1;
  930.                 else
  931.                     Plus = 0;
  932.  
  933.                 while(TopEdge < 0 && TopMost < Info->NumLabels)
  934.                 {
  935.                     TopEdge    += SingleHeight;
  936.                     TopMost    += Plus;
  937.                 }
  938.  
  939.                 DrawInfo = GInfo->gi_DrInfo;
  940.                 Pens = DrawInfo->dri_Pens;
  941.  
  942.                 if(V39)
  943.                 {
  944.                     Info->MenuText = Pens[BARDETAILPEN];
  945.                     Info->MenuBack = Pens[BARBLOCKPEN];
  946.                 }
  947.                 else
  948.                 {
  949.                     Info->MenuText = Pens[DETAILPEN];
  950.                     Info->MenuBack = Pens[BLOCKPEN];
  951.                 }
  952.  
  953.                 Info->CheckGlyph = LTP_CreateCheckGlyph((RPort->TxHeight * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X,RPort->TxHeight,GInfo->gi_Window->RPort->BitMap,Info->MenuText,Info->MenuBack);
  954.  
  955.                 if(Info->CheckGlyph && TopEdge >= 0 && TopMost < Info->NumLabels)
  956.                 {
  957.                     while(Height > SingleHeight && TopEdge + Height > ScreenHeight)
  958.                         Height -= SingleHeight;
  959.  
  960.                     if(Height > SingleHeight && TopEdge + Height <= ScreenHeight)
  961.                     {
  962.                         ReleaseGIRPort(RPort);
  963.  
  964.                         if(Info->Window = OpenWindowTags(NULL,
  965.                             WA_Left,            LeftEdge,
  966.                             WA_Top,                TopEdge,
  967.                             WA_Width,            Width,
  968.                             WA_Height,            Height,
  969.                             WA_SimpleRefresh,    TRUE,
  970.                             WA_NoCareRefresh,    TRUE,
  971.                             WA_AutoAdjust,        FALSE,
  972.                             WA_CustomScreen,    GInfo->gi_Screen,
  973.                             WA_Borderless,        TRUE,
  974.  
  975.                             V39 ? WA_BackFill : TAG_IGNORE,LAYERS_NOBACKFILL,
  976.                         TAG_DONE))
  977.                         {
  978.                             Info->TopMost        = TopMost;
  979.  
  980.                             Info->BoxLeft        = LeftEdge + 4;
  981.                             Info->BoxTop        = TopEdge + 2;
  982.                             Info->BoxWidth        = Width - 8;
  983.                             Info->BoxHeight        = Height - 4;
  984.  
  985.                             Info->BoxLines        = Info->BoxHeight / SingleHeight;
  986.  
  987.                             Info->SingleWidth    = Width - 8;
  988.                             Info->SingleHeight    = SingleHeight;
  989.  
  990.                             if(V39)
  991.                             {
  992.                                 STATIC BYTE RenderPens[] =
  993.                                 {
  994.                                     BACKGROUNDPEN,
  995.                                     FILLPEN,
  996.                                     TEXTPEN,
  997.                                     FILLTEXTPEN,
  998.                                     SHADOWPEN,
  999.                                     SHINEPEN,
  1000.                                     BARDETAILPEN,
  1001.                                     BARBLOCKPEN
  1002.                                     -1
  1003.                                 };
  1004.  
  1005.                                 LONG i,Pen,Max = 0;
  1006.  
  1007.                                 Info->MenuTextSelect    = Pens[BARBLOCKPEN];
  1008.                                 Info->MenuBackSelect    = Pens[BARDETAILPEN];
  1009.  
  1010.                                 for(i = 0 ; RenderPens[i] != -1 ; i++)
  1011.                                 {
  1012.                                     if((Pen = Pens[RenderPens[i]]) > Max)
  1013.                                         Max = Pen;
  1014.                                 }
  1015.  
  1016.                                 SetMaxPen(Info->Window->RPort,Max);
  1017.                             }
  1018.                             else
  1019.                             {
  1020.                                 Info->MenuTextSelect    = ~Pens[DETAILPEN];
  1021.                                 Info->MenuBackSelect    = ~Pens[BLOCKPEN];
  1022.                             }
  1023.  
  1024.                             SetFont(Info->Window->RPort,Info->Font);
  1025.                         }
  1026.  
  1027.                         if(!(RPort = ObtainGIRPort(GInfo)))
  1028.                         {
  1029.                             if(Info->Window)
  1030.                             {
  1031.                                 CloseWindow(Info->Window);
  1032.                                 Info->Window = NULL;
  1033.                             }
  1034.                         }
  1035.                     }
  1036.                 }
  1037.             }
  1038.         }
  1039.  
  1040.         if(!Info->Window)
  1041.         {
  1042.             LTP_DeleteCheckGlyph(Info->CheckGlyph);
  1043.             Info->CheckGlyph = NULL;
  1044.  
  1045.             Info->Flags |= PIF_SingleActive;
  1046.         }
  1047.  
  1048.         if(((Info->Flags & PIF_SingleActive) || Info->Window) && RPort)
  1049.         {
  1050.             Info->InitialActive = Info->Active;
  1051.  
  1052.             gadget->Flags |= GFLG_SELECTED;
  1053.  
  1054.             if(!Info->CheckGlyph)
  1055.                 DoMethod((Object *)gadget,GM_RENDER,GInfo,RPort,GREDRAW_UPDATE);
  1056.  
  1057.             ReleaseGIRPort(RPort);
  1058.  
  1059.             if(Info->Window)
  1060.                 BoxRender(Info,GInfo->gi_DrInfo->dri_Pens,Info->Active,TRUE,TRUE,0);
  1061.  
  1062.             return(GMR_MEACTIVE);
  1063.         }
  1064.  
  1065.         if(RPort)
  1066.             ReleaseGIRPort(RPort);
  1067.     }
  1068.  
  1069.     return(GMR_NOREUSE);
  1070. }
  1071.  
  1072. STATIC ULONG
  1073. InactiveMethod(struct IClass *class,struct Gadget *gadget,struct gpGoInactive *InactiveInfo)
  1074. {
  1075.     PopInfo *Info = INST_DATA(class,gadget);
  1076.  
  1077.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  1078.  
  1079.     gadget->Flags &= ~GFLG_SELECTED;
  1080.  
  1081.     if(Info->Window || (Info->Flags & PIF_SingleActive))
  1082.     {
  1083.         struct RastPort    *RPort;
  1084.  
  1085.         if(Info->Window)
  1086.         {
  1087.             CloseWindow(Info->Window);
  1088.             Info->Window = NULL;
  1089.         }
  1090.  
  1091.         if(!Info->CheckGlyph)
  1092.         {
  1093.             if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  1094.             {
  1095.                 DoMethod((Object *)gadget,GM_RENDER,InactiveInfo->gpgi_GInfo,RPort,GREDRAW_UPDATE);
  1096.                 ReleaseGIRPort(RPort);
  1097.             }
  1098.         }
  1099.  
  1100.         LTP_DeleteCheckGlyph(Info->CheckGlyph);
  1101.         Info->CheckGlyph = NULL;
  1102.  
  1103.         Info->Flags &= ~PIF_SingleActive;
  1104.     }
  1105.  
  1106.     return(0);
  1107. }
  1108.  
  1109. ULONG __saveds __asm
  1110. LTP_PopupClassDispatcher(REG(a0) struct IClass *class,REG(a2) Object *object,REG(a1) Msg msg)
  1111. {
  1112.     switch(msg->MethodID)
  1113.     {
  1114.         case OM_NEW:
  1115.             return(NewMethod(class,object,(struct opSet *)msg));
  1116.  
  1117.         case OM_UPDATE:
  1118.         case OM_SET:
  1119.             SetMethod(class,(struct Gadget *)object,(struct opSet *)msg);
  1120.             break;
  1121.  
  1122.         case GM_RENDER:
  1123.             return(RenderMethod(class,(struct Gadget *)object,(struct gpRender *)msg));
  1124.  
  1125.         case GM_HITTEST:
  1126.             return(GMR_GADGETHIT);
  1127.  
  1128.         case GM_GOINACTIVE:
  1129.             return(InactiveMethod(class,(struct Gadget *)object,(struct gpGoInactive *)msg));
  1130.  
  1131.         case GM_GOACTIVE:
  1132.             return(ActiveMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  1133.  
  1134.         case GM_HANDLEINPUT:
  1135.             return(InputMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  1136.  
  1137.         case OM_DISPOSE:
  1138.             DisposeMethod(class,object,msg);
  1139.  
  1140.             // Falls down to the default case...
  1141.     }
  1142.  
  1143.     return(DoSuperMethodA(class,object,msg));
  1144. }
  1145.  
  1146. #endif    // defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
  1147.